package cn.openea.perpartner.cms.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.openea.perpartner.cms.factory.UserContext;
import cn.openea.perpartner.cms.web.dto.AssignDto;
import cn.openea.perpartner.cms.web.dto.CustomerDto;
import cn.openea.perpartner.cms.web.dto.CustomerLogDto;
import cn.openea.perpartner.cms.web.entity.CmsCommodity;
import cn.openea.perpartner.cms.web.entity.CmsCustomer;
import cn.openea.perpartner.cms.web.entity.CmsCustomerLog;
import cn.openea.perpartner.cms.web.entity.CmsSupplement;
import cn.openea.perpartner.cms.web.mapper.CmsCustomerLogMapper;
import cn.openea.perpartner.cms.web.mapper.CmsCustomerMapper;
import cn.openea.perpartner.cms.web.service.ICmsCommodityService;
import cn.openea.perpartner.cms.web.service.ICmsCustomerService;
import cn.openea.perpartner.cms.web.service.ICmsFavoritesService;
import cn.openea.perpartner.cms.web.service.ICmsSupplementService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.openea.perpartner.cms.web.dto.CustomerCheck;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.utils.StringUtils;
import cn.openea.perpartner.system.util.ToolsUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;

/**
 * (CmsCustomer)表服务实现类
 *
 * @author makejava
 * @since 2022-07-19 22:15:35
 */
@Service("cmsCustomerService")
public class CmsCustomerServiceImpl extends ServiceImpl<CmsCustomerMapper, CmsCustomer> implements ICmsCustomerService {
    private static final Logger log = LoggerFactory.getLogger(CmsCustomerServiceImpl.class);
    /**
     * 未签约
     */
    private static final String NOT_SIGNED = "未签约";
    /**
     * 审核中
     */
    private static final String UNDER_REVIEW = "审核中";
    /**
     * 已签约
     */
    private static final String SIGNED = "已签约";
    /**
     * 已退回
     */
    private static final String RETURNED = "已退回";
    @Value("${date.between}")
    private String dateBetween;

    @Autowired
    private CmsCustomerLogMapper customerLogMapper;
    @Autowired
    private ICmsCommodityService commodityService;
    @Autowired
    private ICmsSupplementService supplementService;
    @Autowired
    private ICmsFavoritesService favorityService;

    /**
     * 通过ID查询单条数据
     *
     * @param unid 主键
     * @return 实例对象
     */
    @Override
    public CustomerDto queryById(Long unid) {
        //获取客户基础数据
        CmsCustomer customer = getById(unid);
        CustomerDto customerDto = new CustomerDto();
        customerDto.setCustomer(customer);

        //获取跟踪记录数据
        LambdaQueryWrapper<CmsCustomerLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CmsCustomerLog::getCustomerId, unid);
        wrapper.eq(CmsCustomerLog::getUserid, UserContext.getUserId());
        List<CmsCustomerLog> customerLogList = customerLogMapper.selectList(wrapper);

        List<CustomerLogDto> logList = new ArrayList<>();
        for (CmsCustomerLog customerLog : customerLogList) {
            CustomerLogDto customerLogDto = new CustomerLogDto();
            customerLogDto.setCustomerLogId(customerLog.getUnid());
            customerLogDto.setContent(customerLog.getContent());
            customerLogDto.setCreateTime(customerLog.getCreatetime());
            String createDate = DateUtil.parseDate(customerLog.getCreatetime()).toDateStr();
            String nowDate = DateUtil.today();
            //判断记录是否当天创建的，当天记录是可以编辑的
            customerLogDto.setEdit(nowDate.equals(createDate));
            logList.add(customerLogDto);
        }
        customerDto.setLogData(logList);
        return customerDto;
    }

    /**
     * 修改数据
     */
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean save(CustomerDto customerDto) {
        //将前端customerDto数据对象转为为customer对象，取客户基础数据
        boolean isSuccess;
        CmsCustomer customer = customerDto.getCustomer();
        //更新基础数据
        String openeaId = customer.getOpeneaId();
        if (StrUtil.isBlank(openeaId)) {
            openeaId = ToolsUtil.autoUserID();
            customer.setOpeneaId(openeaId);
        }
        if (ObjectUtil.isEmpty(customer.getUnid())) {
            customer.setCreateUser(UserContext.getUserId());
            customer.setUpdateUser(UserContext.getUserId());
            customer.setNickName(UserContext.getUserName());
            customer.setUnid(IdUtil.getSnowflake(1, 1).nextId());
        }

        isSuccess = saveOrUpdate(customer);
        //从customerDto对象取任务跟踪记录数据
        List<CustomerLogDto> customerLogDtoList = customerDto.getLogData();
        List<Long> logIdList = new ArrayList<>();
        for (CustomerLogDto customerLogDto : customerLogDtoList) {
            logIdList.add(customerLogDto.getCustomerLogId());
        }
        if (logIdList.isEmpty()){
            return isSuccess;
        }
        LambdaQueryWrapper<CmsCustomerLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CmsCustomerLog::getUnid, logIdList);
        wrapper.eq(CmsCustomerLog::getUserid, UserContext.getUserId());
        List<CmsCustomerLog> customerLogList = customerLogMapper.selectList(wrapper);
        //insert,第一次跟踪记录
        int len = customerLogDtoList.size() - 1;
        CustomerLogDto customerLogDto = customerLogDtoList.get(len);
        if (customerLogList.isEmpty()) {
            CmsCustomerLog customerLog = new CmsCustomerLog();
            customerLog.setUserid(UserContext.getUserId());
            customerLog.setCustomerId(customer.getUnid());
            customerLog.setContent(customerLogDto.getContent());
            return customerLogMapper.insert(customerLog) > 0;
        }
        //insert n+1次跟踪记录
        if (logIdList.size() > customerLogList.size()) {
            CmsCustomerLog customerLog = new CmsCustomerLog();
            customerLog.setUserid(UserContext.getUserId());
            customerLog.setCustomerId(customer.getUnid());
            customerLog.setContent(customerLogDto.getContent());
            isSuccess = customerLogMapper.insert(customerLog) > 0;
        }
        //update
        for (int i = 0; i < customerLogList.size(); i++) {
            customerLogDto = customerLogDtoList.get(i);
            //跟踪记录不变，则不进行数据更新
            if (customerLogList.get(i).getContent().equals(customerLogDto.getContent())) {
                continue;
            }
            customerLogList.get(i).setContent(customerLogDto.getContent());
            isSuccess = customerLogMapper.updateById(customerLogList.get(i)) > 0;
        }
        return isSuccess;
    }

    @Override
    public List<CmsCustomer> selectList(String userId, String searchStr) {
        LambdaQueryWrapper<CmsCustomer> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(userId)) {
            wrapper.eq(CmsCustomer::getUpdateUser, userId);
        }
        if (StrUtil.isNotBlank(searchStr)) {
            boolean isStatus = false;
            if (NOT_SIGNED.contains(searchStr)) {
                searchStr = "0";
                isStatus = true;
            }
            if (UNDER_REVIEW.contains(searchStr)) {
                searchStr = "1";
                isStatus = true;
            }
            if (SIGNED.contains(searchStr)) {
                searchStr = "2";
                isStatus = true;
            }
            if (RETURNED.contains(searchStr)) {
                searchStr = "3";
                isStatus = true;
            }
            if (isStatus) {
                wrapper.eq(CmsCustomer::getSigningStatus, searchStr);
            } else if (StringUtils.isNumeric(searchStr)) {
                Date date = DateUtil.offsetDay(DateUtil.date(), -Integer.parseInt(searchStr));
                String dateTime = DateUtil.formatDate(date);
                wrapper.like(CmsCustomer::getUpdatetime, dateTime);
            } else {
                String finalSearchStr = searchStr;
                wrapper.and(wrap -> wrap.like(CmsCustomer::getPlatform, finalSearchStr)
                        .or().like(CmsCustomer::getCompany, finalSearchStr)
                        .or().like(CmsCustomer::getProduct, finalSearchStr)
                        .or().like(CmsCustomer::getNickName, finalSearchStr)
                        .or().like(CmsCustomer::getTelphone, finalSearchStr)
                        .or().like(CmsCustomer::getIntention, finalSearchStr)
                        .or().like(CmsCustomer::getContacts, finalSearchStr)
                        .or().like(CmsCustomer::getBrand, finalSearchStr)
                        .or().like(CmsCustomer::getCategory, finalSearchStr)
                );
            }
        }
        wrapper.orderByAsc(CmsCustomer::getUpdatetime);
        wrapper.orderByDesc(CmsCustomer::getIntention);
        List<CmsCustomer> customerList = this.baseMapper.selectList(wrapper);
        for (CmsCustomer customer : customerList) {
            long dateBetween = DateUtil.between(DateUtil.parseDate(customer.getUpdatetime()), DateUtil.date(), DateUnit.DAY);
            customer.setDateBetween(dateBetween);
        }
        return customerList;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public String importCustomer(List<CmsCustomer> customerList) {
        if (StringUtils.isNull(customerList) || customerList.isEmpty()) {
            throw new ServiceException("导入客户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (CmsCustomer customer : customerList) {
            try {
                Map<String, Object> columMap = BeanUtil.beanToMap(customer);
                columMap.remove("unid");
                //若此条记录内容全部为空，则跳过不导入
                boolean hasNullColumn = true;
                for (Map.Entry<String, Object> entry : columMap.entrySet()) {
                    if (StrUtil.isNotEmpty((String) entry.getValue())) {
                        hasNullColumn = false;
                        break;
                    }
                }
                if (hasNullColumn) {
                    continue;
                }
                long uid = IdUtil.getSnowflake(1, 1).nextId();
                customer.setUnid(uid);
                customer.setOpeneaId(ToolsUtil.autoUserID());
                customer.setCreateUser(UserContext.getUserId());
                customer.setUpdateUser(UserContext.getUserId());
                customer.setNickName(UserContext.getUserName());
                save(customer);
                if (StrUtil.isNotEmpty(customer.getContext())) {
                    CmsCustomerLog cmsCustomerLog = new CmsCustomerLog();
                    cmsCustomerLog.setContent(customer.getContext());
                    cmsCustomerLog.setCustomerId(customer.getUnid());
                    cmsCustomerLog.setUserid(UserContext.getUserId());
                    customerLogMapper.insert(cmsCustomerLog);
                }
                successNum++;
                successMsg.append("<br/>").append(successNum).append("、客户 ").append(customer.getCompany()).append(" 导入成功");
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、客户 " + customer.getCompany() + " 导入失败：";
                failureMsg.append(msg).append(e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean recycle(List<Long> idList) {
        LambdaUpdateWrapper<CmsCustomer> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CmsCustomer::getUnid, idList);
        //回收前，同时删除销售的收藏记录
        List<CmsCustomer> customerList = list(wrapper);
        customerList.forEach(customer -> favorityService.deleteByLinkId(customer.getUnid(), customer.getUpdateUser()));
        //批量更新状态
        wrapper.set(CmsCustomer::getStatus, "2")
                .set(CmsCustomer::getUpdateUser, "")
                .set(CmsCustomer::getNickName, "");
        return update(wrapper);
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean assign(List<AssignDto> assignList) throws Exception {
        boolean isSuccess = false;
        for (AssignDto dto : assignList) {
            CmsCustomer customer = baseMapper.selectById(dto.getAssignId());
            customer.setStatus("0");
            customer.setUpdateUser(dto.getUserId());
            customer.setNickName(dto.getUserName());
            isSuccess = updateById(customer);
        }
        return isSuccess;
    }

    @Override
    public List<Object> selectLogList(int offset) {
        //获取当前时间
        DateTime dateTime = DateUtil.offsetWeek(new DateTime(), offset);
        LambdaUpdateWrapper<CmsCustomerLog> wrapper = new LambdaUpdateWrapper<>();
        //获取当前周第一天
        String startTime = DateUtil.beginOfWeek(dateTime).toDateStr();
        //获取当前周最后一天
        String endTime = DateUtil.offsetDay(DateUtil.endOfWeek(dateTime), 1).toDateStr();
        wrapper.between(CmsCustomerLog::getCreatetime, startTime, endTime);
        wrapper.eq(CmsCustomerLog::getUserid, UserContext.getUserId());
        List<CmsCustomerLog> customerLogList = customerLogMapper.selectList(wrapper);
        Map<String, Integer> map = new HashMap<>();
        for (CmsCustomerLog customerLog : customerLogList) {
            String createTime = customerLog.getCreatetime();
            String week = DateUtil.dayOfWeekEnum(DateUtil.parseDate(createTime)).toChinese("周");
            if (map.containsKey(week)) {
                map.put(week, map.get(week) + 1);
            } else {
                map.put(week, 1);
            }
        }
        List<Object> logList = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            JSONObject obj = new JSONObject();
            obj.put("weekDay", entry.getKey());
            obj.put("workNum", entry.getValue() + "条");
            logList.add(obj);
        }
        return logList;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean approveContract(Serializable id) {
        CmsCustomer customer = baseMapper.selectById(id);
        //商品生成19位编号，状态设为已签约，即入库
        List<CmsCommodity> commodityList = commodityService.selectList(customer.getUnid().toString());
        commodityList.forEach(commodity -> {
            //取品牌商家公司名称
            commodity.setCompany(customer.getCompany());
            LambdaQueryWrapper<CmsSupplement> wrap = new LambdaQueryWrapper<>();
            wrap.eq(CmsSupplement::getCustomerId, customer.getUnid());
            CmsSupplement supplement = supplementService.getOne(wrap);
            commodity.setShopName(supplement.getShopName());
            commodity.setTaobaoDistribution(supplement.getTaobaoDistribution());
            commodity.setOtherDistribution(supplement.getOtherDistribution());
            commodity.setCommunityDistribution(supplement.getCommunityDistribution());
            commodity.setSigningStatus("2");
            commodity.setCommodityNum(ToolsUtil.autoUserID(2));
            commodity.setCommodityStatus("未定价");
            commodityService.updateById(commodity);
        });
        customer.setSigningStatus("2");
        return updateById(customer);
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean refuseContract(Serializable id, String content) {
        CmsCustomer customer = baseMapper.selectById(id);
        //插入退回理由到跟进记录
        CmsCustomerLog customerLog = new CmsCustomerLog();
        customerLog.setCustomerId(customer.getUnid());
        customerLog.setContent(content);
        customerLog.setUserid(customer.getUpdateUser());
        customerLogMapper.insert(customerLog);
        //将商品表设为退回状态
        List<CmsCommodity> commodityList = commodityService.selectList(customer.getUnid().toString());
        commodityList.forEach(commodity -> {
            commodity.setSigningStatus("3");
            commodityService.updateById(commodity);
        });
        //将主表设为退回状态
        customer.setSigningStatus("3");
        return updateById(customer);
    }

    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean applyContract(Serializable id) {
        CmsCustomer customer = baseMapper.selectById(id);
        List<CmsCommodity> commodityList = commodityService.selectList(customer.getUnid().toString());
        commodityList.forEach(commodity -> {
            commodity.setSigningStatus("1");
            commodityService.updateById(commodity);
        });
        customer.setSigningStatus("1");
        return updateById(customer);
    }

    @Override
    public List<CmsCustomer> selectList(String searchStr) {
        LambdaQueryWrapper<CmsCustomer> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(searchStr)) {
            wrapper.and(wrap -> wrap.like(CmsCustomer::getPlatform, searchStr)
                    .or().like(CmsCustomer::getCompany, searchStr)
                    .or().like(CmsCustomer::getProduct, searchStr)
                    .or().like(CmsCustomer::getNickName, searchStr)
                    .or().like(CmsCustomer::getTelphone, searchStr)
                    .or().like(CmsCustomer::getIntention, searchStr)
                    .or().like(CmsCustomer::getContacts, searchStr)
            );
        }
        wrapper.eq(CmsCustomer::getSigningStatus, "1");
        wrapper.orderByAsc(CmsCustomer::getUpdatetime);
        wrapper.orderByDesc(CmsCustomer::getIntention);
        List<CmsCustomer> customerList = this.baseMapper.selectList(wrapper);
        for (CmsCustomer customer : customerList) {
            long dateBetween = DateUtil.between(DateUtil.parseDate(customer.getUpdatetime()), DateUtil.date(), DateUnit.DAY);
            customer.setDateBetween(dateBetween);
        }
        return customerList;
    }

    @Override
    public boolean check(String customerId) {
        CmsCustomer customer = baseMapper.selectById(customerId);
        if (BeanUtil.isEmpty(customer)) {
            return false;
        }
        CustomerCheck customerCheck = new CustomerCheck();
        BeanUtil.copyProperties(customer, customerCheck);
        Map<String, Object> customerMap = BeanUtil.beanToMap(customerCheck);
        for (Map.Entry<String, Object> entry : customerMap.entrySet()) {
            if (ObjectUtil.isEmpty(entry.getValue())) {
                return false;
            }
        }
        return true;
    }


    /**
     * 超过十天自动回收
     */
    public void autoRecycle() {
        List<CmsCustomer> customerList = this.selectList("", "");
        List<Long> list = new ArrayList<>();
        for (CmsCustomer customer : customerList) {
            long dayBetween = DateUtil.between(DateUtil.parse(customer.getUpdatetime()), DateUtil.date(), DateUnit.DAY);
            if (dayBetween > Long.parseLong(dateBetween)) {
                list.add(customer.getUnid());
            }
        }
        if (!list.isEmpty()) {
            this.recycle(list);
        }
    }
}
